package com.wechatpay.v3.sdk;

import com.wechatpay.v3.vo.WechatResult;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.*;
import com.wechatpay.v3.constants.WechatPayResultCode;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;

/**
 * @author liuyi <liuy@pvc123.com>
 * @since 2021/7/23
 */
public class WechatPayRequest {

    private final Logger logger = LoggerFactory.getLogger(WechatPayRequest.class);

    private final WechatConfig wechatConfig;

    private final PrivateKey privateKey;

    private Verifier verifier;

    private CloseableHttpClient closeableHttpClient;

    public WechatPayRequest(WechatConfig wechatConfig, PrivateKey privateKey) {

        this.wechatConfig = wechatConfig;
        this.privateKey = privateKey;

        try {
            init();
        } catch (Exception e) {
            logger.error("WechatPayRequest init fail",e);
            throw new RuntimeException("WechatPayRequest init fail",e);
        }
    }

    private void init() throws Exception {

        // merchantId商户号
        // merchantSerialNumber商户API证书的证书序列号。
        // merchantPrivateKey商户API私钥
        // wechatpayCertificates微信支付平台证书
        PrivateKey merchantPrivateKey = this.privateKey;
        String merchantId = wechatConfig.getMchID();
        String merchantSerialNumber = wechatConfig.getMerchantSerialNumber();
        String apiV3Key = wechatConfig.getApiV3Key();

        // 自动更新证书, 指定自动更新时间为12小时
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                new WechatPay2Credentials(merchantId, new PrivateKeySigner(merchantSerialNumber, merchantPrivateKey)),
                apiV3Key.getBytes(StandardCharsets.UTF_8),AutoUpdateCertificatesVerifier.TimeInterval.TwelveHours.getMinutes());
        this.setVerifier(verifier);
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(this.wechatConfig.getMchID(),
                        this.wechatConfig.getMerchantSerialNumber(),
                        merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier));
        // 通过WechatPayHttpClientBuilder构造的HttpClient，会自动的处理签名和验签
        this.closeableHttpClient = builder.build();
    }

    public WechatResult requestPost(String url, String jsonParams) throws Exception {
        logger.info("wechat sdk -> post url:{}",url);
        logger.info("wechat sdk -> jsonParams:{}",jsonParams);
        CloseableHttpClient httpClient = this.closeableHttpClient;

        URIBuilder uriBuilder = new URIBuilder(url);
        HttpPost httpPost = new HttpPost(uriBuilder.build());

        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type","application/json; charset=utf-8");

        httpPost.setEntity(new StringEntity(jsonParams, "UTF-8"));
        CloseableHttpResponse response = httpClient.execute(httpPost);
        String responseStr = "";
        if (null != response.getEntity()) {
            responseStr = EntityUtils.toString(response.getEntity());
        }
        if(response.getStatusLine().getStatusCode() == 200 || response.getStatusLine().getStatusCode() == 204) {
            return new WechatResult(WechatPayResultCode.SUCCESS,responseStr);
        }
        return new WechatResult(WechatPayResultCode.FAILURE,responseStr);
    }

    public WechatResult requestGet(String url) throws Exception {
        logger.info("wechat sdk -> get url:{}",url);

        CloseableHttpClient httpClient = this.closeableHttpClient;

        URIBuilder uriBuilder = new URIBuilder(url);
        HttpGet httpGet = new HttpGet(uriBuilder.build());

        httpGet.addHeader("Accept", "application/json");
        httpGet.addHeader("Content-type","application/json; charset=utf-8");


        CloseableHttpResponse response = httpClient.execute(httpGet);
        String responseStr = EntityUtils.toString(response.getEntity());

        if(response.getStatusLine().getStatusCode() == 200) {
            return new WechatResult(WechatPayResultCode.SUCCESS,responseStr);
        }
        return new WechatResult(WechatPayResultCode.FAILURE,responseStr);
    }

    public Verifier getVerifier() {
        return verifier;
    }

    public WechatPayRequest setVerifier(Verifier verifier) {
        this.verifier = verifier;
        return this;
    }
}
